package org.example.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author: sql
 * @date: 2024/6/7
 * @Description: 日期工具
 * @version: 1.0
 */
public final class DateUtil {

    public static final Map<String, SimpleDateFormat> simpleDateMap = new ConcurrentHashMap<>();
    /**
     * 时间格式
     */
    public final static String DATE_PATTERN = "yyyy-MM-dd";
    public static final String DATE_FORMAT = "yyyy-MM-dd";
    public static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String DATE_FORMAT_SHORT = "yyyyMMdd";
    public static final String DATE_TIME_FORMAT_SHORT = "yyyyMMddHHmmss";
    public static final String TIME_FORMAT = "HH:mm:ss";
    public static final String TIME_FORMAT_SHORT = "HHmmss";

    /**
     * 取年份
     *
     * @param date
     * @return
     */
    public static int getYear(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.get(Calendar.YEAR);
    }

    /**
     * 取月份
     *
     * @param date
     * @return
     */
    public static int getMonth(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.get(Calendar.MONTH) + 1;
    }

    /**
     * 取日期
     *
     * @param date
     * @return
     */
    public static int getDate(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.get(Calendar.DATE);
    }


    /**
     * 转日期对象
     *
     * @param source
     * @return
     */
    public static Date parseDate(String source) {
        return parse(source, DATE_FORMAT);
    }

    /**
     * 转日期时间对象
     *
     * @param source
     * @return
     */
    public static Date parseDateTime(String source) {
        return parse(source, DATE_TIME_FORMAT);
    }


    /**
     * 转日期对象
     *
     * @param source
     * @param format
     * @return
     */
    public static Date parse(String source, String format) {
        Date date = null;
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        try {
            date = sdf.parse(source);
        } catch (Exception ex) {
        }
        return date;
    }

    /**
     * 转日期格式字符串
     *
     * @param date
     * @return
     */
    public static String formatDate(Date date) {
        return format(date, DATE_FORMAT);
    }

    /**
     * 转日期格式字符串
     *
     * @param date
     * @return
     */
    public static String formatDateShort(Date date) {
        return format(date, DATE_FORMAT_SHORT);
    }


    /**
     * 转日期格式字符串
     *
     * @param timeInMillions
     * @return
     */
    public static String formatDate(long timeInMillions) {
        return format(timeInMillions, DATE_FORMAT);
    }

    /**
     * 转日期格式字符串
     *
     * @param timeInMillions
     * @return
     */
    public static String formatDateShort(long timeInMillions) {
        return format(timeInMillions, DATE_FORMAT_SHORT);
    }

    /**
     * 转日期时间格式字符串
     *
     * @param date
     * @return
     */
    public static String formatDateTime(Date date) {
        return format(date, DATE_TIME_FORMAT);
    }

    /**
     * 转日期时间格式字符串
     *
     * @param date
     * @return
     */
    public static String formatDateTimeShort(Date date) {
        return format(date, DATE_TIME_FORMAT_SHORT);
    }

    /**
     * 转日期时间格式字符串
     *
     * @param timeInMillions
     * @return
     */
    public static String formatDateTime(long timeInMillions) {
        return format(timeInMillions, DATE_TIME_FORMAT);
    }

    /**
     * 转日期时间格式字符串
     *
     * @param timeInMillions
     * @return
     */
    public static String formatDateTimeShort(long timeInMillions) {
        return format(timeInMillions, DATE_TIME_FORMAT_SHORT);
    }


    /**
     * 转时间格式字符串
     *
     * @param date
     * @return
     */
    public static String formatTime(Date date) {
        return format(date, TIME_FORMAT);
    }

    /**
     * 转时间格式字符串
     *
     * @param date
     * @return
     */
    public static String formatTimeShort(Date date) {
        return format(date, TIME_FORMAT_SHORT);
    }


    /**
     * 转时间格式字符串
     *
     * @param timeInMillions
     * @return
     */
    public static String formatTime(long timeInMillions) {
        return format(timeInMillions, TIME_FORMAT);
    }

    /**
     * 转时间格式字符串
     *
     * @param timeInMillions
     * @return
     */
    public static String formatTimeShort(long timeInMillions) {
        return format(timeInMillions, TIME_FORMAT_SHORT);
    }


    /**
     * 当前日期转字符串
     *
     * @return
     */
    public static String formatCurrentDate() {
        return format(new Date(), DATE_FORMAT);
    }

    /**
     * 当前日期时间转字符串
     *
     * @return
     */
    public static String formatCurrentDateTime() {
        return format(new Date(), DATE_TIME_FORMAT);
    }

    /**
     * 当前日期时间转字符串
     *
     * @return
     */
    public static String formatCurrentDateTimeShort() {
        return format(new Date(), DATE_TIME_FORMAT_SHORT);
    }

    /**
     * 转字符串
     *
     * @param timeInMillions
     * @param format
     * @return
     */
    public static String format(long timeInMillions, String format) {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        try {
            Date date = new Date(timeInMillions);
            return sdf.format(date);
        } catch (Exception ex) {
        }
        return null;
    }


    /**
     * 转 java.sql.Date
     *
     * @param date
     * @return
     */
    public static java.sql.Date toSqlDate(Date date) {
        return new java.sql.Date(date.getTime());
    }

    /**
     * 转 java.util.Date
     *
     * @param date
     * @return
     */
    public static Date toDate(java.sql.Date date) {
        return new Date(date.getTime());
    }

    /**
     * 取当前年份
     *
     * @return
     */
    public static int getCurrentYear() {
        Calendar c = Calendar.getInstance();
        return c.get(Calendar.YEAR);
    }


    /**
     * 返回清空时间后的日历对象
     *
     * @return
     */
    public static Calendar getDateCalendar() {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        return c;
    }

    /**
     * @param src
     * @param src
     * @param days
     * @return
     */
    public static Calendar addDays(Calendar src, int days) {
        src.add(Calendar.DAY_OF_MONTH, days);
        return src;
    }

    public static Date addDays(Date currentDate, int days) {
        // 使用Calendar进行日期加减
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(currentDate);
        calendar.add(Calendar.DAY_OF_MONTH, days);
        return calendar.getTime();
    }


    /**
     * @param src
     * @param workdays
     * @return
     */
    public static Calendar addWorkDays(Calendar src, int workdays) {
        int days = 0;
        int step = 1;
        if (workdays < 0) step = -1;
        workdays = Math.abs(workdays);
        while (days < workdays) {
            src.add(Calendar.DAY_OF_MONTH, step);
            if (!isWorkDay(src)) continue;
            days++;
        }
        return src;
    }

    /**
     * 判断是否为工作日
     *
     * @param c
     * @return
     */
    public static boolean isWorkDay(Calendar c) {
        int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);
        /*周六日被认为不是工作日*/
        if (dayOfWeek == Calendar.SUNDAY || dayOfWeek == Calendar.SATURDAY) return false;
        return true;
    }

    public static String dateDiff(String startTime, String endTime, String format) throws ParseException {
        //按照传入的格式生成一个simpledateformate对象
        SimpleDateFormat sd = new SimpleDateFormat(format);
        long nd = 1000 * 24 * 60 * 60;//一天的毫秒数
        long nh = 1000 * 60 * 60;//一小时的毫秒数
        long nm = 1000 * 60;//一分钟的毫秒数
        long ns = 1000;//一秒钟的毫秒数
        long diff;
        //获得两个时间的毫秒时间差异
        diff = sd.parse(endTime).getTime() - sd.parse(startTime).getTime();
        long day = diff / nd;//计算差多少天
        long hour = diff % nd / nh;//计算差多少小时
        long min = diff % nd % nh / nm;//计算差多少分钟
        long sec = diff % nd % nh % nm / ns;//计算差多少秒//输出结果
        String diffStr = day + "";
        return diffStr;
//		System.out.println("时间相差："+day+"天"+hour+"小时"+min+"分钟"+sec+"秒。");
    }


    /**
     * 根据日期类型获取日期格式化对象
     *
     * @param pattern 日期格式
     * @return SimpleDateFormat
     */
    public static SimpleDateFormat getSimpleDateFormat(String pattern) {
        SimpleDateFormat sft = null;
        if ((sft = simpleDateMap.get(pattern)) == null) {
            sft = new SimpleDateFormat(pattern);
            simpleDateMap.put(pattern, sft);
        }
        return sft;
    }

    /**
     * 获取日期格式化字符串
     *
     * @param date    指定日期
     * @param pattern 日期格式
     * @return String
     */
    public static String format(Date date, String pattern) {
        return getSimpleDateFormat(pattern).format(date);
    }

    /**
     * 获取yyyy-MM-dd格式的日期
     *
     * @param date 需要格式化的日期
     * @return String
     */
    public static String formatYMD(Date date) {
        return format(date, DATE_PATTERN);
    }

    /**
     * 获取当前日期
     *
     * @param pattern 日期格式
     * @return String
     */
    public static String getCurrentDate(String pattern) {
        return getSimpleDateFormat(pattern).format(new Date());
    }

    /**
     * 获取时间戳
     *
     * @return long
     */
    public static long getTimestamp() {
        return System.currentTimeMillis();
    }

    /**
     * 获取星期几
     *
     * @param date
     * @return
     */
    public static int getWeekDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.DAY_OF_WEEK) - 1;
    }


    //-----------------------------------------------------------------------
    /**
     * Adds a number of months to a date returning a new object.
     * The original {@code Date} is unchanged.
     *
     * @param date  the date, not null
     * @param amount  the amount to add, may be negative
     * @return the new {@code Date} with the amount added
     * @throws IllegalArgumentException if the date is null
     */
    public static Date addMonths(final Date date, final int amount) {
        return add(date, Calendar.MONTH, amount);
    }

    private static Date add(final Date date, final int calendarField, final int amount) {
        if (date == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
        final Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(calendarField, amount);
        return c.getTime();
    }
}
